/**
 * 
 */
package com.geezdata.cps.ttk.core.command;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.quartz.JobDetail;
import org.quartz.ScheduleBuilder;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.core.jmx.JobDetailSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.geezdata.cps.base.enums.ErrorCode;
import com.geezdata.cps.base.exceptions.MyException;
import com.geezdata.cps.base.response.BaseResponse;
import com.geezdata.cps.base.vo.SendModeVO;
import com.geezdata.cps.cqrs.command.Command;
import com.geezdata.cps.ttk.common.factory.CreateJobResultFactory;
import com.geezdata.cps.ttk.common.request.CreateJobRequest;
import com.geezdata.cps.ttk.common.response.CreateJobResult;
import com.geezdata.cps.ttk.common.util.CronExpressionUtil;
import com.geezdata.cps.ttk.common.vo.JobVO;
import com.geezdata.cps.ttk.domain.domain.Job;
import com.geezdata.cps.ttk.domain.factory.JobFactory;
import com.geezdata.cps.ttk.mapper.mapper.JobMapper;

/**
 * @author sszheng
 * @date 创建时间：2017年9月25日 下午4:02:37
 *
 */
@Service
@ConditionalOnBean(Scheduler.class)
public class CreateJobCommand implements Command<CreateJobRequest, CreateJobResult> {
	private static final Logger logger = LoggerFactory.getLogger(CreateJobCommand.class);
	
	@Autowired
    private Scheduler scheduler;
	@Autowired
	private JobMapper jobMapper;
	
	@Transactional
	@Override
	public BaseResponse<CreateJobResult> execute(CreateJobRequest request) {
		try {
			Job job = JobFactory.newInstance(request.getJob());
			jobMapper.insertSelective(job);
			
			JobVO jobVO = request.getJob();
			
			String jobClassName = job.getClassName();
			String triggerName = job.getTriggerName();
			String triggerGroup = job.getTriggerGroup();
			String jobName = job.getJobName();
			String jobGroup = job.getJobGroup();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);
            if (scheduler.checkExists(triggerKey)) {
            	logger.error("该任务已存在. triggerName: " + triggerKey.getName() + ", triggerGroup: " + triggerKey.getGroup());
            	throw new MyException(ErrorCode.INTERNAL_SERVER_ERROR.getCode(), "该任务已存在");
            }
            
            JobDetail jobDetail = buildJobDetail(jobName, jobGroup, jobClassName);
			scheduler.addJob(jobDetail, true);
			
            Trigger trigger = buildTrigger(triggerName, triggerGroup, jobVO.getSendModeVO(), jobVO.getParams(), jobDetail);
            scheduler.scheduleJob(trigger);
            if(!scheduler.isStarted()) {
            	scheduler.start();// ⑤调度启动
            }
            
            return BaseResponse.success(CreateJobResultFactory.newInstance(triggerName));
        } catch (Exception e) {
        	logger.error(e.getMessage(), e);
        	return BaseResponse.error(ErrorCode.INTERNAL_SERVER_ERROR.getCode(), ErrorCode.INTERNAL_SERVER_ERROR.getDesc());
        }
	}

	private Trigger buildTrigger(String triggerName, String triggerGroup, SendModeVO sendModeVO, String params, JobDetail jobDetail) {
		Date startDate = null;
		Date endDate = null;
		ScheduleBuilder<?> schedBuilder = null;
		switch (sendModeVO.getSendType()) {
		case 1:
			startDate = new Date();
			schedBuilder = simpleSchedule().withRepeatCount(0);
			break;
		case 2:
			startDate = sendModeVO.getStartTime();
			schedBuilder = simpleSchedule().withRepeatCount(0);
			break;
		case 3:
			startDate = sendModeVO.getStartTime().before(new Date()) ? new Date(): sendModeVO.getStartTime();
			endDate = sendModeVO.getEndTime();
			schedBuilder = cronSchedule(CronExpressionUtil.getCronExpression(sendModeVO));
			break;
		default:
			logger.error("error send type: " + sendModeVO.getSendType());
			throw new MyException(ErrorCode.INTERNAL_SERVER_ERROR);
		}
		
		return TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroup).usingJobData("params", params).forJob(jobDetail)
				.startAt(startDate).endAt(endDate).withSchedule(schedBuilder).build();
	}
	
	private JobDetail buildJobDetail(String jobName, String jobGroup, String jobClassName) throws ClassNotFoundException {
		Map<String, Object> JobDetailmap = new HashMap<String, Object>();
        JobDetailmap.put("name", jobName);// 设置任务名字
        JobDetailmap.put("group", jobGroup);// 设置任务组
        JobDetailmap.put("jobClass", jobClassName);// 指定执行类
        JobDetail jobDetail = JobDetailSupport.newJobDetail(JobDetailmap).getJobBuilder().storeDurably(true).build();
		return jobDetail;
	}
}
